#!/usr/bin/python

from google.appengine.api import users
from google.appengine.ext import db

import copy
import json
import webapp2


class GameModel(db.Model):
  game = db.StringProperty(required = True)
  name = db.StringProperty(required = True)
  players = db.ListProperty(str, required = True)
  is_public = db.BooleanProperty(required = True)
  owner = db.StringProperty(required = True)
  data = db.TextProperty(required = True)
  create_time = db.DateTimeProperty(auto_now_add = True)
  modify_time = db.DateTimeProperty(auto_now = True)


def CreateGameEntity(game, name, players, is_public, owner):
  '''Creates a game entity.

  Args:
  game: a string indiciating what game it is.
  name: name of the game.
  players: a list of players, can be email, 'ai', or 'public'.
  is_public: is the game public?
  owner: the email of the game owner.

  Returns:
  A numeric game ID.
  '''
  data = {
      'private': {          # private game data
          'state': 'Init',  # game state
          },
      'players': {},        # user dict indexed by email
      }

  entity = GameModel(game = game, name = name, players = players,
                     is_public = is_public, owner = owner,
                     data = json.dumps(data))
  entity.put()
  return entity.key().id()


def GetGameEntity(game_id):
  '''Returns the game entity.

  Args:
  game_id: numeric game ID.

  Returns:
  The game entity or None if not found.
  '''
  return GameModel.get_by_id(game_id)


class BaseGame(object):
  def __init__(self, config, game_entity, request, response):
    self.config = config
    self.game_entity = game_entity
    self.data = json.loads(self.game_entity.data)
    self.request = request
    self.response = response

  def GetName(self):
    return self.game_entity.name

  def IsPublic(self):
    return self.game_entity.is_public

  def IsOwner(self):
    user = users.get_current_user()
    return user and user.email() == self.game_entity.owner

  def IsInGame(self):
    user = users.get_current_user()
    return user and user.email() in self.game_entity.players

  def GetCreateTime(self):
    return self.game_entity.create_time

  def GetModifyTime(self):
    return self.game_entity.modify_time

  def GetData(self):
    return self.data

  def IsLoggedIn(self):
    return not not users.get_current_user()

  def PackDataForClient(self):
    # Removes private info from data. Only the user's own private info will be
    # kept.
    client_data = copy.deepcopy(self.data)
    if 'private' in client_data:
      del(client_data['private'])
    user = users.get_current_user()
    if 'players' in client_data:
      for user_id, user_data in client_data['players'].iteritems():
        if (((not user) or user_id != user.user_id()) and
            'private' in user_data):
          del(user_data['private'])
    # Add data from config and game entity.
    clinet_data['config'] = self.config
    clinet_data['game'] = self.game_entity.game
    # XXX: not finished

  def Process(self, action):
    if not self.IsPublic() and not self.IsInGame():
      if not users.get_current_user():
        webapp2.redirect(users.create_login_url(self.request.url),
                         abort = True)
      else:
        webapp2.abort(404)

    # Dispatch the request to the correspoing state handler.
    state = self.GetData()['private']['state']
    return getattr(self, 'Handle' + state)(action)

  def HandleInit(self, action):
    self.response.content_type = 'text/html'
    self.response.headers.add('Cache-Control', 'no-cache')
    self.response.out.write('ok')
